/* DHTServer - ESP8266 Webserver with a DHT sensor as an input

   Based on ESP8266Webserver, DHTexample, and BlinkWithoutDelay (thank you)

   Version 1.0  5/3/2014  Version 1.0   Mike Barela for Adafruit Industries
*/
#include "defines.h"
#include <Adafruit_NeoPixel.h>
#include <WebSockets2_Generic.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#define DHTTYPE DHT11
#define DHTPIN  2
// Replace with your network details


using namespace websockets2_generic;

WebsocketsClient client;
int status=0;//连接状态,初始为 0 代表关闭
void onEventsCallback(WebsocketsEvent event, String data) 
{
  if (event == WebsocketsEvent::ConnectionOpened) 
  {
    Serial.println("Connnection Opened");
    status=1;
  } 
  else if (event == WebsocketsEvent::ConnectionClosed) 
  {
    Serial.println("Connnection Closed");
status=0;
  } 
  else if (event == WebsocketsEvent::GotPing) 
  {
    Serial.println("Got a Ping!");
  } 
  else if (event == WebsocketsEvent::GotPong) 
  {
    Serial.println("Got a Pong!");
  }
}


 
// Initialize DHT sensor 
// NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
// you need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// This is for the ESP8266 processor on ESP-01 
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
 
float humidity, temp_f;  // Values read from sensor
String webString="";     // String to display
// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0;        // will store last temp was read
const long interval = 2000;              // interval at which to read sensor
 

 
void setup(void)
{
  // You can open the Arduino IDE Serial Monitor window to see what the code is doing
  Serial.begin(115200);  // Serial connection from ESP-01 via 3.3v console cable
  dht.begin();           // initialize temperature sensor

  // Connect to WiFi network
  WiFi.begin(ssid, password);
  Serial.print("\n\r \n\rWorking to connect");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("DHT Weather Reading Server");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
   
  Serial.print("Connected to Wifi, Connecting to WebSockets Server @");
   Serial.println(websockets_server_host); 
     client.addHeader("Origin", "http://"+String(websockets_server_host));//设置来源地址,保持和服务器地址一致,防止跨域被拦截,默认是当前库的 github 地址
    //client.addHeader("Authorization", "Basic YWRtaW46YWRtaW4="); //如果使用的是原始的库,并且使用的是spring security 因为会默认添加无数据的Authorization头,可能会出现 401,需要添加账号密码 ,或者修改库的底层源码去掉默认添加的 Authorization 空头,内容是Basic 账号:密码的base64,可以通过修改库的底层源码去掉默认空的认证信息
  
  // run callback when messages are received
  client.onMessage([&](WebsocketsMessage message) 
  {
    Serial.print("Got Message: ");
     String command =message.data(); //获取到服务端发来的数据
     Serial.print(command);
     Serial.print("\n");
    if(command =="0"){ //如果服务器发送的是 0 则设置状态为 0 低电平
    
    }
    else if(command =="1"){//如果服务器发送的是 1 则设置状态为 1 高电平
     // Serial.println("1");
     
    }
    
  });

  // run callback when events are occuring
  client.onEvent(onEventsCallback); //设置websocket 的回调
}



void sendMessage(void)
{
// try to connect to Websockets server
  //连接方式 1
  bool connected = client.connect(websockets_server_host, websockets_server_port, "/humiture/ht1234567890"); //和服务器连接,主机和地址在 defines 文件中声明
   //连接方式 2
  //bool connected =  client.connect("ws://"+String(websockets_server_host)+":"+String(websockets_server_port)+"/websocket/1234567890"); //比如ws://192.168.3.2/websocket/aaaa

  if (connected) 
  {
    Serial.println("Connected!");
    status=1; //连接后修改状态为已连接
    //String WS_msg = String("Hello to Server from ") + BOARD_NAME;
    //client.send(WS_msg); //随便发送了一条消息
  } 
  else 
  {
    Serial.println("Not Connected!");
  }
}

void checkToSendMessage()
{
  #define REPEAT_INTERVAL    20000L
  
  static unsigned long checkstatus_timeout = 0;

  // Send WebSockets message every REPEAT_INTERVAL (10) seconds.
  //重连检查,每 10 秒检查一下,如果是关闭状态则重新连接
  if (((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))&&status==0)
  {
    sendMessage();
    checkstatus_timeout = millis() + REPEAT_INTERVAL;
  }else if (((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))&&status==1){//如果是连接状态,则每 20 秒发送一条 ping 消息
   // client.send("ping");
    gettemperature();       // read sensor
   // webString="wenshidu: "+String((int)temp_f)+" F          "+String((int)humidity)+"%"; 
   webString="{\"humidity\":"+String(humidity)+",\"temperature\":"+String(temp_f)+"}";
    client.send(webString);
    checkstatus_timeout = millis() + REPEAT_INTERVAL;
    }
}
//初始循环
 
void loop(void)
{
  checkToSendMessage();
  
  // let the websockets client check for incoming messages
  if (client.available()) 
  {
    client.poll();
  }
} 

void gettemperature() {
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    // save the last time you read the sensor 
    previousMillis = currentMillis;   

    // Reading temperature for humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
    humidity = dht.readHumidity();          // Read humidity (percent)
    temp_f = dht.readTemperature(true);     // Read temperature as Fahrenheit
    // Check if any reads failed and exit early (to try again).
    if (isnan(humidity) || isnan(temp_f)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
  }
}
